package main

import (
	"fmt"
	"net"
	"net/http"
	"net/http/httputil"

	"github.com/gorilla/mux"
	"github.com/micro/cli"
	"github.com/micro/go-micro/cmd"
	"github.com/micro/go-micro/selector"
	"github.com/micro/go-micro/selector/cache"
	"qiniupkg.com/x/log.v7"
)

var (
	CORS = map[string]bool{"*": true}
)

type srv struct {
	*mux.Router
}

func (s *srv) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if origin := r.Header.Get("Origin"); CORS[origin] {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	} else if len(origin) > 0 && CORS["*"] {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	}

	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
	w.Header().Set("Access-Control-Allow-Credentials", "true")

	if r.Method == "OPTIONS" {
		return
	}

	s.Router.ServeHTTP(w, r)
}

func (s *srv) proxy() http.Handler {
	sel := cache.NewSelector(
		selector.Registry((*cmd.DefaultOptions().Registry)),
	)

	director := func(r *http.Request) {
		kill := func() {
			r.URL.Host = ""
			r.URL.Path = ""
			r.URL.Scheme = ""
			r.Host = ""
			r.RequestURI = ""
		}
		host, _, _ := net.SplitHostPort(r.Host)
		next, err := sel.Select(host)
		if err != nil {
			kill()
			return
		}

		s, err := next()
		if err != nil {
			kill()
			return
		}

		r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port)
		r.URL.Scheme = "http"
		r.Host = r.URL.Host
	}

	return &proxy{
		Default:  &httputil.ReverseProxy{Director: director},
		Director: director,
	}
}

func run(ctx *cli.Context) {
	s := &srv{mux.NewRouter()}
	s.PathPrefix("/").Handler(s.proxy())

	log.Panic(http.ListenAndServe(":8877", s))
}

func main() {
	log.SetOutputLevel(0)
	run(nil)
}
